﻿using MicrosoftLogLevel = Microsoft.Extensions.Logging.LogLevel;

namespace MicroCloud.Log4Net
{
    /// <summary>
    /// log4net日志记录
    /// </summary>
    public class Log4NetLogger : ILogger
    {
        //字段
        private readonly ILog _logger;

        #region 构造函数
        /// <summary>
        /// 初始化一个log4net日志记录 <see cref="Log4NetLogger"/> 的新实例
        /// </summary>
        /// <param name="loggerRepository"></param>
        /// <param name="name"></param>
        public Log4NetLogger(string loggerRepository, string name)
        {
            _logger = LogManager.GetLogger(loggerRepository, name);
        }

        #endregion

        #region 方法
        /// <summary>写入日志项</summary>
        /// <param name="logLevel">日志级别，将按这个级别写不同的日志</param>
        /// <param name="eventId">事件编号.</param>
        /// <param name="state">要写的条目。也可以是一个对象</param>
        /// <param name="exception">与此项相关的异常</param>
        /// <param name="formatter">函数创建 <paramref name="state"/> 和 <paramref name="exception"/> 的 <c>string</c> 消息</param>
        public void Log<TState>(MicrosoftLogLevel logLevel, EventId eventId, TState state, System.Exception exception, Func<TState, System.Exception, string> formatter)
        {
            if (!IsEnabled(logLevel))
            {
                return;
            }

            Check.NotNull(formatter, nameof(formatter));
            string message = null;
            if (formatter != null)
            {
                message = formatter(state, exception);
            }

            if (!string.IsNullOrEmpty(message) || exception != null)
            {
                switch (logLevel)
                {
                    case MicrosoftLogLevel.Trace:
                    case MicrosoftLogLevel.Debug:
                        _logger.Debug(message);
                        break;
                    case MicrosoftLogLevel.Information:
                        _logger.Info(message);
                        break;
                    case MicrosoftLogLevel.Warning:
                        _logger.Warn(message);
                        break;
                    case MicrosoftLogLevel.Error:
                        _logger.Error(message, exception);
                        break;
                    case MicrosoftLogLevel.Critical:
                        _logger.Fatal(message, exception);
                        break;
                    case MicrosoftLogLevel.None:
                        break;
                    default:
                        _logger.Warn($"遇到未知的日志级别 {logLevel}, 使用 Info 级别写入日志。");
                        _logger.Info(message, exception);
                        break;
                }
            }
        }

        /// <summary>
        /// 检查给定的 <paramref name="logLevel" /> 是否已启用
        /// </summary>
        /// <param name="logLevel">要检查的级别</param>
        /// <returns><c>true</c> if enabled.</returns>
        public bool IsEnabled(MicrosoftLogLevel logLevel)
        {
            return logLevel switch
            {
                MicrosoftLogLevel.Trace or MicrosoftLogLevel.Debug => _logger.IsDebugEnabled,
                MicrosoftLogLevel.Information => _logger.IsInfoEnabled,
                MicrosoftLogLevel.Warning => _logger.IsWarnEnabled,
                MicrosoftLogLevel.Error => _logger.IsErrorEnabled,
                MicrosoftLogLevel.Critical => _logger.IsFatalEnabled,
                MicrosoftLogLevel.None => false,
                _ => throw new ArgumentOutOfRangeException(nameof(logLevel), logLevel, null),
            };
        }

        /// <summary>开始逻辑操作范围</summary>
        /// <param name="state">作用域的标识符</param>
        /// <returns>在dispose时结束逻辑操作作用域的IDisposable</returns>
        public IDisposable BeginScope<TState>(TState state)
        {
            return null;
        }

        #endregion

    }

}
